package com.bjbn.service;

import com.bjbn.model.VehicleData;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

@Service
@Slf4j
public class FzLocation1Service {

    @Autowired
    private KafkaProducerService kafkaProducerService;

    @Value("${csv.directory.fz-location-1:../doc/fz-location-1}")
    private String fzLocation1Directory;

    @Value("${csv.topic}")
    private String topic;

    // 存储每个CSV文件的数据
    private Map<String, List<VehicleData>> csvDataMap = new ConcurrentHashMap<>();
    // 每个CSV文件的当前索引
    private Map<String, AtomicInteger> csvIndexMap = new ConcurrentHashMap<>();
    // 每个CSV文件的运行状态
    private Map<String, Boolean> csvRunningMap = new ConcurrentHashMap<>();
    // 总记录数
    private final AtomicLong totalRecords = new AtomicLong(0);
    // 线程池
    private ExecutorService executorService;

    // 时间格式化器
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // JSON解析器
    private final ObjectMapper objectMapper = new ObjectMapper();

    @PostConstruct
    public void init() {
        loadFzLocation1Data();
    }

    public void loadFzLocation1Data() {
        log.info("Loading FZ-Location-1 data from directory: {}", fzLocation1Directory);

        try {
            Path directory = Paths.get(fzLocation1Directory);
            if (!Files.exists(directory)) {
                log.error("FZ-Location-1 directory does not exist: {}", fzLocation1Directory);
                return;
            }

            File[] csvFiles = directory.toFile().listFiles((dir, name) -> name.toLowerCase().endsWith(".csv"));

            if (csvFiles == null || csvFiles.length == 0) {
                log.warn("No CSV files found in FZ-Location-1 directory: {}", fzLocation1Directory);
                return;
            }

            log.info("Found {} CSV files in FZ-Location-1 directory", csvFiles.length);

            // 清空现有数据
            csvDataMap.clear();
            csvIndexMap.clear();
            csvRunningMap.clear();
            totalRecords.set(0);

            // 加载所有CSV文件
            for (int i = 0; i < csvFiles.length; i++) {
                loadFzLocation1CsvFile(csvFiles[i], i);
            }


            // 创建线程池，线程数等于CSV文件数量，确保每个文件都有独立线程
            if (executorService != null) {
                executorService.shutdown();
            }
            executorService = Executors.newFixedThreadPool(csvFiles.length);

            log.info("Loaded {} CSV files from FZ-Location-1 with {} total records, created {} threads",
                    csvFiles.length, totalRecords.get(), csvFiles.length);

        } catch (Exception e) {
            log.error("Error loading FZ-Location-1 CSV files: {}", e.getMessage(), e);
        }
    }

    private void loadFzLocation1CsvFile(File csvFile, int index) {
        log.info("Loading FZ-Location-1 CSV file: {}", csvFile.getName());

        List<VehicleData> fileData = new ArrayList<>();

        try (FileReader reader = new FileReader(csvFile);
             CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withHeader())) {

            for (CSVRecord record : csvParser) {
                VehicleData data = parseFzLocation1CsvRecord(record, index);
                fileData.add(data);
            }

            // 将文件数据存储到对应的映射中
            String fileName = csvFile.getName();
            csvDataMap.put(fileName, fileData);
            csvIndexMap.put(fileName, new AtomicInteger(0));
            csvRunningMap.put(fileName, false);
            totalRecords.addAndGet(fileData.size());

            log.info("Loaded {} records from FZ-Location-1 file {}", fileData.size(), fileName);

        } catch (IOException e) {
            log.error("Error loading FZ-Location-1 CSV file {}: {}", csvFile.getName(), e.getMessage(), e);
        }
    }

    private VehicleData parseFzLocation1CsvRecord(CSVRecord record, int index) {
        String vehicleId = String.format("民航-%04d", index);
        return new VehicleData(
                vehicleId,
                getFzLocation1Value(record, "EMPLOYEEID"),
                vehicleId,
                1,
                getFzLocation1Value(record, "GEOX"),
                getFzLocation1Value(record, "GEOY"),
                getFzLocation1Value(record, "GEOH"),
                getFzLocation1Value(record, "ANGLE"), // ANGLE对应DIRECTION
                getFzLocation1Value(record, "LL_TIME"),
                getFzLocation1Value(record, "SPEED"),
                "引导车",
                getFzLocation1Value(record, "VI_REMARK"),
                "Y",
                getFzLocation1Value(record, "GROUP_NAME"),
                getFzLocation1Value(record, "SIMCODE"),
                getFzLocation1Value(record, "SIGN"),
                getFzLocation1Value(record, "LOCALCOORDY"),
                getFzLocation1Value(record, "LOCALCOORDX"),
                1,
                parseFzLocation1LabelParams(vehicleId),
                "车辆标签",
                "vehicle"
        );
    }

    private Map<String, Object> parseFzLocation1LabelParams(String vehicleId) {
        Map<String, Object> labelParams = new HashMap<>();
        labelParams.put("text", vehicleId);
        /*
          {
            "text": "民航-0026",
            "iconVis": false,
            "frameVis": true,
            "frameColor": "00AAFFFF",
            "frameOpacity": 1,
            "textBgColor": "00AAFFFF",
            "textBgOpacity": 0.5,
            CATEGORY:"vehicle"
          }
        * */
        labelParams.put("carNumber", vehicleId);
        labelParams.put("carType", "引导车");
        labelParams.put("iconVis", false);
        labelParams.put("frameVis", true);
        labelParams.put("frameColor", "00AAFFFF");
        labelParams.put("frameOpacity", 1);
        labelParams.put("textBgColor", "00AAFFFF");
        labelParams.put("textBgOpacity", 0.5);
        labelParams.put("CATEGORY", "vehicle");

        return labelParams;
    }

    private String convertFzLocation1PythonDictToJson(String pythonDictStr) {
        if (pythonDictStr == null || pythonDictStr.trim().isEmpty()) {
            return "{}";
        }

        // 移除首尾的空白字符
        String trimmed = pythonDictStr.trim();

        // 如果已经是JSON格式，直接返回
        if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
            // 检查是否包含单引号（Python格式）
            if (trimmed.contains("'")) {
                // 将单引号替换为双引号
                return trimmed.replace("'", "\"");
            }
            return trimmed;
        }

        // 如果不是字典格式，返回空对象
        return "{}";
    }

    private String getFzLocation1Value(CSVRecord record, String columnName) {
        try {
            return record.get(columnName);
        } catch (IllegalArgumentException e) {
            log.warn("Column '{}' not found in FZ-Location-1 CSV record", columnName);
            return "";
        }
    }

    private Integer getFzLocation1IntValue(CSVRecord record, String columnName) {
        try {
            return Integer.parseInt(record.get(columnName));
        } catch (IllegalArgumentException e) {
            log.warn("Column '{}' not found in FZ-Location-1 CSV record", columnName);
            return null;
        }
    }

    @Async
    public void startFzLocation1ContinuousProcessing() {
        if (csvDataMap.isEmpty()) {
            log.error("No FZ-Location-1 CSV data loaded. Please load CSV files first.");
            return;
        }

        log.info("Starting FZ-Location-1 continuous processing for {} CSV files", csvDataMap.size());

        // 为每个CSV文件启动独立的处理线程
        for (String fileName : csvDataMap.keySet()) {
            executorService.submit(() -> processFzLocation1CsvFile(fileName));
        }
    }

    private void processFzLocation1CsvFile(String fileName) {
        List<VehicleData> fileData = csvDataMap.get(fileName);
        AtomicInteger currentIndex = csvIndexMap.get(fileName);

        if (fileData == null || fileData.isEmpty()) {
            log.warn("No data found for FZ-Location-1 file: {}", fileName);
            return;
        }

        // 设置文件为运行状态
        csvRunningMap.put(fileName, true);

        log.info("FZ-Location-1 file {} starting processing immediately", fileName);

        log.info("Starting FZ-Location-1 continuous processing for file: {} with {} records", fileName, fileData.size());

        while (csvRunningMap.get(fileName)) {
            try {
                // 获取当前时间作为推送时间
                String currentTime = LocalDateTime.now().format(formatter);

                // 获取当前索引的数据
                int index = currentIndex.getAndIncrement() % fileData.size();
                VehicleData data = fileData.get(index);

                // 更新LL_TIME为当前推送时间
                data.setLL_TIME(currentTime);

                // 使用文件名作为消息key
                String messageKey = "fz-location-1_" + fileName;
                kafkaProducerService.sendMessage(messageKey, data);

                log.debug("Sent FZ-Location-1 record {}/{} from file {} to Kafka at {}",
                        index + 1, fileData.size(), fileName, currentTime);

                // 等待1秒
                Thread.sleep(1000);

            } catch (InterruptedException e) {
                log.info("FZ-Location-1 file {} processing interrupted", fileName);
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                log.error("Error during processing FZ-Location-1 file {}: {}", fileName, e.getMessage(), e);
            }
        }

        log.info("Stopped FZ-Location-1 continuous processing for file: {}", fileName);
    }

    public void stopFzLocation1ContinuousProcessing() {
        log.info("Stopping FZ-Location-1 continuous processing for all CSV files");
        for (String fileName : csvRunningMap.keySet()) {
            csvRunningMap.put(fileName, false);
        }
    }

    public boolean isFzLocation1Running() {
        return csvRunningMap.values().stream().anyMatch(running -> running);
    }

    public long getFzLocation1TotalRecords() {
        return totalRecords.get();
    }

    public Map<String, Object> getFzLocation1DetailedStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("isRunning", isFzLocation1Running());
        status.put("totalRecords", totalRecords.get());
        status.put("totalFiles", csvDataMap.size());

        Map<String, Object> fileStatus = new HashMap<>();
        for (String fileName : csvDataMap.keySet()) {
            Map<String, Object> fileInfo = new HashMap<>();
            fileInfo.put("isRunning", csvRunningMap.get(fileName));
            fileInfo.put("currentIndex", csvIndexMap.get(fileName).get());
            fileInfo.put("totalRecords", csvDataMap.get(fileName).size());
            fileStatus.put(fileName, fileInfo);
        }
        status.put("fileStatus", fileStatus);

        return status;
    }

    public void reloadFzLocation1Data() {
        log.info("Reloading FZ-Location-1 CSV data...");
        stopFzLocation1ContinuousProcessing();
        loadFzLocation1Data();
    }

    public Set<String> getFzLocation1LoadedFiles() {
        return new HashSet<>(csvDataMap.keySet());
    }

    @PreDestroy
    public void destroyFzLocation1() {
        if (executorService != null && !executorService.isShutdown()) {
            log.info("Shutting down FZ-Location-1 executor service...");
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}
